package py.com.alfa.escriba.web.services.impl;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.util.CollectionUtils;

import py.com.alfa.escriba.exception.ErrorCode;
import py.com.alfa.escriba.exception.ServiceException;
import py.com.alfa.escriba.persistence.dao.AdminDAO;
import py.com.alfa.escriba.persistence.dao.DatoscomplementariosDAO;
import py.com.alfa.escriba.persistence.dao.DatosportemplateDAO;
import py.com.alfa.escriba.persistence.dao.VehiculosDAO;
import py.com.alfa.escriba.persistence.dao.VehiculosinfoDAO;
import py.com.alfa.escriba.persistence.dto.DatosportemplateDTO;
import py.com.alfa.escriba.persistence.dto.VehiculosDTO;
import py.com.alfa.escriba.persistence.dto.VehiculosinfoDTO;
import py.com.alfa.escriba.persistence.dto.referencia.TabRefDTO;
import py.com.alfa.escriba.util.ObjectUtils;
import py.com.alfa.escriba.util.Utils;
import py.com.alfa.escriba.web.interceptor.InvocationContext;
import py.com.alfa.escriba.web.services.VehiculosService;

public class VehiculosServiceImpl implements VehiculosService{
	
  private Logger log = LoggerFactory.getLogger(getClass());
  private VehiculosDAO vehiculosDAO;
  private VehiculosinfoDAO vehiculosInfoDAO;
  private AdminDAO adminDAO;
  private DatosportemplateDAO datosportemplateDAO;
  private DatoscomplementariosDAO datoscomplementariosDAO;
  

public void setAdminDAO(AdminDAO adminDAO) {
	this.adminDAO = adminDAO;
}

public void setVehiculosDAO(VehiculosDAO vehiculosDAO) {
    this.vehiculosDAO = vehiculosDAO;
}

public void setVehiculosInfoDAO(VehiculosinfoDAO vehiculosInfoDAO) {
	this.vehiculosInfoDAO = vehiculosInfoDAO;
}

public void setDatosportemplateDAO(DatosportemplateDAO datosportemplateDAO) {
	this.datosportemplateDAO = datosportemplateDAO;
}

public void setDatoscomplementariosDAO(DatoscomplementariosDAO datoscomplementariosDAO) {
	this.datoscomplementariosDAO = datoscomplementariosDAO;
}

@Override
  public List<VehiculosDTO> listVehiculos(InvocationContext ic) throws ServiceException {
	VehiculosDTO v = new VehiculosDTO();
	v.setIdescribano(ic.getIdEscribano());
    List<VehiculosDTO> vehiculoss =  vehiculosDAO.listVehiculos(v);

    return vehiculoss;
  }

  @Override
  public List<VehiculosinfoDTO> listDatosVehiculosInfo(InvocationContext ic) throws ServiceException {
	List<VehiculosinfoDTO> vehiculosinfos =  vehiculosInfoDAO.listDatosVehiculosInfo();

	return vehiculosinfos;
  }

  @Override
  public VehiculosDTO getVehiculos(Long id, InvocationContext ic) throws ServiceException {
    if (id == null || id <= 0)
      throw new ServiceException(ErrorCode.PARAMETER_ERROR,"parameter.error.null","id");

    VehiculosDTO vehiculos =  vehiculosDAO.getVehiculosById(id);

    if (vehiculos == null)
      throw new ServiceException(ErrorCode.NO_DATA_FOUND,"vehiculos.notfound", id);
    
    List<VehiculosinfoDTO> vehiculosInfo = new ArrayList<VehiculosinfoDTO>();
//    vehiculosInfo= vehiculosInfoDAO.listVehiculosInfoByIdVehiculo(vehiculos.getId());
    vehiculosInfo= vehiculosInfoDAO.listDatosVehiculosInfoById(vehiculos.getId());
    vehiculos.setVehiculosInfo(vehiculosInfo);
    
    return vehiculos;
  }

  @Override
  public void deleteVehiculos(Long id, InvocationContext ic) throws ServiceException {
    if (id == null || id <= 0)
      throw new ServiceException(ErrorCode.PARAMETER_ERROR,"parameter.error.null","id");

    VehiculosDTO vehiculos =  vehiculosDAO.getVehiculosById(id);

    if(vehiculos == null)
      throw new ServiceException(ErrorCode.NO_DATA_FOUND,"vehiculos.notfound", id);

    try {
      vehiculosInfoDAO.deleteVehiculosinfoByIdVehiculo(id);
      vehiculosDAO.deleteVehiculos(vehiculos);
    }
    catch (DataIntegrityViolationException e){
      log.error(e.getMessage(),e);
      throw new ServiceException(ErrorCode.DATA_INTEGRITY_VIOLATION, "vehiculos.constraint.violation", id);
    }

  }

  @Override
  public VehiculosDTO updateVehiculos(Long id, VehiculosDTO dto, InvocationContext ic) throws ServiceException {
    if (id == null || id <= 0)
      throw new ServiceException(ErrorCode.PARAMETER_ERROR,"parameter.error.null","id");

    if (null == dto)
      throw new ServiceException(ErrorCode.PARAMETER_ERROR,"parameter.error.null","dto");

    VehiculosDTO vehiculos = vehiculosDAO.getVehiculosById(id);

    if (vehiculos == null)
      throw new ServiceException(ErrorCode.NO_DATA_FOUND,"vehiculos.notfound", id);
    
    if(dto.getNroserie()==null && dto.getNrochasis()==null){
  	  throw new ServiceException(ErrorCode.PARAMETER_ERROR,"vehiculo.vehiculo.not.serie.chasis.error");
    }
    if(dto.getChapa()!=null){
  	  
  	 VehiculosDTO v= vehiculosDAO.validarChapaExisteneteByEscribano(dto);
  	 if(!id.equals(v.getId())){
  		 throw new ServiceException(ErrorCode.PARAMETER_ERROR,"vehiculo.vehiculo.exists.escribano");
  	 }
    }

    Utils.validarDTO(dto);

    dto.setTrn(vehiculosDAO.getTrnVehiculos()+1L);
    dto.setIdusuariomodificacion(ic.getIdUserPrincipal());
    dto.setFechamodificacion(new Date(System.currentTimeMillis()));
    vehiculosDAO.updateVehiculos(dto);
    
    /*if(!CollectionUtils.isEmpty(dto.getEliminadosVehiculosInfo())){
    	for(Long idDel:dto.getEliminadosVehiculosInfo()){
        	VehiculosinfoDTO del = new VehiculosinfoDTO();
        	del.setId(idDel);
        	vehiculosInfoDAO.deleteVehiculosinfo(del);
        }
    }*/
    
    //validacion de datosComplementarios
//    validarVehiculosInfo(dto.getVehiculosInfo());
    validarDatosPorTemplate(dto);
    
    if(!CollectionUtils.isEmpty(dto.getVehiculosInfo())){
    	vehiculosInfoDAO.deleteVehiculosinfoByIdVehiculo(dto.getId());
    	/*for(VehiculosinfoDTO vi:dto.getVehiculosInfo()){
    		vi.setIddato(vi.getDatoComplementario().getId());
    		vi.setIdvehiculo(dto.getId());
    		if(vi.getId() == null){
    			validarVehiculoInfo(vi);
    			vehiculosInfoDAO.createVehiculosinfo(vi);
    		}
    	}*/
        for(VehiculosinfoDTO vi:dto.getVehiculosInfo()){
      	  if(ObjectUtils.isNotEmpty(vi.getValor()) || vi.getValorDate() != null || vi.getValorInteger() != null ){
      		  validarVehiculoInfo(vi);
      		  vi.setIddato(vi.getDatoComplementario().getId());
          	  vi.setIdvehiculo(dto.getId());
          	  vehiculosInfoDAO.createVehiculosinfo(vi);  
      	  }	  
        }
    }
    
    return dto;
  }

  @Override
  public VehiculosDTO createVehiculos(VehiculosDTO dto, InvocationContext ic) throws ServiceException {
    if (dto == null)
      throw new ServiceException(ErrorCode.PARAMETER_ERROR,"parameter.error.null","dto");
    
    if (ic.getIdEscribano() == null)
        throw new ServiceException(ErrorCode.PARAMETER_ERROR,"parameter.error.null","escribano");

    try {

      Utils.validarDTO(dto);
      if(dto.getNroserie()==null && dto.getNrochasis()==null){
    	  throw new ServiceException(ErrorCode.PARAMETER_ERROR,"vehiculo.vehiculo.not.serie.chasis.error");
      }
      if(dto.getChapa()!=null){
    	  
    	 VehiculosDTO v= vehiculosDAO.validarChapaExisteneteByEscribano(dto);
    	 if(v!=null){
    		 throw new ServiceException(ErrorCode.PARAMETER_ERROR,"vehiculo.vehiculo.exists.escribano");
    	 }
      }
      Long trn = vehiculosDAO.getTrnVehiculos();
      dto.setTrn(trn+1L);
      dto.setIdescribano(ic.getIdEscribano());
      dto.setIdusuario(ic.getIdUserPrincipal());
      dto.setFechacreacion(new Date(System.currentTimeMillis()));
      vehiculosDAO.createVehiculos(dto);
      //validacion de datosComplementarios
//      validarVehiculosInfo(dto.getVehiculosInfo());
      validarDatosPorTemplate(dto);
      for(VehiculosinfoDTO vi:dto.getVehiculosInfo()){
    	  if(ObjectUtils.isNotEmpty(vi.getValor()) || vi.getValorDate() != null || vi.getValorInteger() != null ){
    		  validarVehiculoInfo(vi);
    		  vi.setIddato(vi.getDatoComplementario().getId());
        	  vi.setIdvehiculo(dto.getId());
        	  vehiculosInfoDAO.createVehiculosinfo(vi);  
    	  }	  
      }
      
    }
    catch (DuplicateKeyException e){
      throw new ServiceException(ErrorCode.DUPLICATE_KEY_EXCEPTION, "vehiculos.duplicate.key");
    }

    return dto;
  }

  @SuppressWarnings("unused")
  private void validarVehiculosInfo(List<VehiculosinfoDTO> list) throws ServiceException{
	  for(VehiculosinfoDTO vi:list){
		  validarVehiculoInfo(vi);
      }
  }
  
  private void validarVehiculoInfo(VehiculosinfoDTO vi) throws ServiceException{
	  vi.setDatoComplementario(datoscomplementariosDAO.getDatoscomplementariosById(vi.getIddato()));
	  log.info("\n=========\nVALIDAR VEHICULO: {}\n=========\n", vi);
	  TabRefDTO tipoDato = adminDAO.getTabRefsById(vi.getDatoComplementario().getIdtipodato().longValue());
	  log.info("\n=========\nTIPO DE DATO: {}\n=========\n", tipoDato);
	  if ("INTEGER".equals(tipoDato.getCodigo())){
		  if(ObjectUtils.isEmpty(vi.getValor()) && vi.getValorInteger()==null){
			  throw new ServiceException(ErrorCode.PARAMETER_ERROR,"vehiculo.valor.nulo");
		  }
		  if(ObjectUtils.isNotEmpty(vi.getValor())){
			  try {
				  vi.setValorInteger(Long.parseLong(vi.getValor()));
			  }catch (NumberFormatException e) {
				log.error(e.getMessage(), e);
				throw new ServiceException(ErrorCode.PARAMETER_ERROR,"valor.integer.formato.error",vi.getValor());
			  }
		  }
		  vi.setValor(""+vi.getValorInteger());
		  if (vi.getValor().length() > vi.getDatoComplementario().getLongitud()){
			  throw new ServiceException(ErrorCode.PARAMETER_ERROR,"valor.supera.longitud.error", vi.getDatoComplementario().getLongitud(), vi.getValor());
		  }
	  }
	  if ("STRING".equals(tipoDato.getCodigo())){
		  if(ObjectUtils.isEmpty(vi.getValor())){
			  throw new ServiceException(ErrorCode.PARAMETER_ERROR,"vehiculo.valor.nulo");
		  }
		  if (vi.getValor().length() > vi.getDatoComplementario().getLongitud()){
			  throw new ServiceException(ErrorCode.PARAMETER_ERROR,"valor.supera.longitud.error", vi.getDatoComplementario().getLongitud(), vi.getValor());
		  }
	  }
	  if ("DATE".equals(tipoDato.getCodigo())){
		  if(ObjectUtils.isEmpty(vi.getValor()) && vi.getValorDate()==null){
			  throw new ServiceException(ErrorCode.PARAMETER_ERROR,"vehiculo.valor.nulo");
		  }
		  SimpleDateFormat sdf= new SimpleDateFormat(vi.getDatoComplementario().getMascara());
		  if(ObjectUtils.isNotEmpty(vi.getValor())){
			try {
				vi.setValorDate(sdf.parse(vi.getValor()));
			} catch (ParseException e) {
				log.error(e.getMessage(), e);
				throw new ServiceException(ErrorCode.PARAMETER_ERROR,"valor.date.formato.error",vi.getValor());
			}  
		  }
		  vi.setValor(sdf.format(vi.getValorDate()));
	  }
  }
  
  private void validarDatosPorTemplate(VehiculosDTO dto){
	  List<VehiculosinfoDTO> list=dto.getVehiculosInfo();
	  List<DatosportemplateDTO> dpt = datosportemplateDAO.listDatosportemplateByIdTemp(dto.getIdtemplatecertificado());
	  Boolean tiene;
	  for(DatosportemplateDTO dp :dpt){
		  tiene=false;
		  for(VehiculosinfoDTO vi: list){
			  if(dp.getIddatocomplementario().equals(vi.getDatoComplementario().getId())){
				  tiene=true;
				  break;
			  }
		  }
		  if(!tiene){
			  throw new ServiceException(ErrorCode.PARAMETER_ERROR,"vehiculo.datoscomplementaris.incompleto");
		  }
		  
	  }
	  
	  
  }

  @Override
  public List<VehiculosDTO> buscarVehiculos(VehiculosDTO dto, InvocationContext ic) 	throws ServiceException {
	  if (dto == null)
		  throw new ServiceException(ErrorCode.PARAMETER_ERROR,"parameter.error.null","dto");
	  dto.setIdescribano(ic.getIdEscribano());
	  if(dto.getChapa()!= null && !dto.getChapa().equals("")){
		  dto.setChapa("%"+dto.getChapa()+"%");
	  }
	  if(dto.getNrochasis()!=null && !dto.getNrochasis().equals("")){
		  dto.setNrochasis("%"+dto.getNrochasis()+"%");
	  }
	  if(dto.getNroserie()!=null && !dto.getNroserie().equals("")){
		  dto.setNroserie("%"+dto.getNroserie()+"%");
	  }
	  List<VehiculosDTO> vehiculoss =  vehiculosDAO.buscarVehiculos(dto);
	  return vehiculoss;
  }

  
  

}